/** @file    CoderXML_Xtended.cpp
 *  @author  Alessandro Polo
 *  @version $Id: CoderXML_Xtended.cpp 1825 2010-02-12 13:07:08Z alex $
 *  @brief
 * File containing methods for Serialization.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include <framework/database/CoderXML_Xtended.h>

 #include <framework/database/CoderXML_Core.h>
 #include <framework/database/EncoderXML.h>


using namespace std;
using namespace wosh::xtended;
namespace wosh {
 namespace database {

void EncoderXML_register_Xtended()
 {
	EncoderXML::registerDataType( _WeatherInfo_TYPE,	new EncoderXML_template__WeatherInfo() );
	EncoderXML::registerDataType( _ManPage_TYPE,		new EncoderXML_template__ManPage() );
	EncoderXML::registerDataType( _ManItem_TYPE,		new EncoderXML_template__ManItem() );
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ManItem::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const wosh::xtended::ManItem* object = dynamic_cast<const wosh::xtended::ManItem*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;
	(void)compact;

	contNode.setAttribute("name", QString(object->getName().c_str()) );

	QDomElement descrNode = doc.createElement("description");
	descrNode.appendChild( doc.createTextNode( QString(object->getDescription().c_str()) ) );
	contNode.appendChild(descrNode);

	if ( !object->getReferences().empty() ) {
		QDomElement refsNode = doc.createElement("references");
		for( unsigned int j=0; j<object->getReferences().size(); ++j ) {
			QDomElement keywordNode = doc.createElement("see");
			keywordNode.setAttribute("type", QString(object->getReferences().at(j).type.c_str()) );
			keywordNode.appendChild( doc.createTextNode( QString(object->getReferences().at(j).name.c_str()) ) );
			refsNode.appendChild(keywordNode);
		 }
		contNode.appendChild(refsNode);
	 }

	if ( !object->getKeywords().empty() ) {
		QDomElement keywNode = doc.createElement("keywords");
		for( unsigned int j=0; j<object->getKeywords().size(); j++ ) {
			QDomElement keywordNode = doc.createElement("keyword");
			keywordNode.appendChild( doc.createTextNode( QString(object->getKeywords().at(j).name.c_str()) ) );
			keywNode.appendChild(keywordNode);
		 }
		contNode.appendChild(keywNode);
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ManItem::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	wosh::xtended::ManItem* object = dynamic_cast<wosh::xtended::ManItem*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement nameNode = contNode.namedItem("name").toElement();
	if ( nameNode.isNull() )
		object->setName( string( contNode.attribute("name").toLatin1().data() ) );
	else
		object->setName( string( nameNode.text().toLatin1().data() ) );

	QDomElement descrNode = contNode.namedItem("description").toElement();
	if ( descrNode.isNull() )
		object->setDescription( string( contNode.attribute("description").toLatin1().data() ) );
	else
		object->setDescription( string( descrNode.text().toLatin1().data() ) );

	QDomElement refNode = contNode.namedItem("references").toElement();
	if ( !refNode.isNull() ) {
		QDomNodeList refList = refNode.childNodes();
		for( unsigned int j=0; j<refList.length(); j++ ) {
			QDomElement childNode = refList.item(j).toElement();
			ManReference refEntry;
			refEntry.name = string(childNode.text().toLatin1().data());
			refEntry.type = string(childNode.attribute("type").toLatin1().data());
			object->getReferences().push_back(refEntry);
		 }
	 }

	QDomElement keywNode = contNode.namedItem("keywords").toElement();
	if ( !keywNode.isNull() ) {
		QDomNodeList keywList = keywNode.childNodes();
		for( unsigned int j=0; j<keywList.length(); j++ ) {
			QDomElement childNode = keywList.item(j).toElement();
			ManKeyword keyworkEntry;
			keyworkEntry.name = string(childNode.text().toLatin1().data());
			object->getKeywords().push_back(keyworkEntry);
		 }
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ManSection::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const wosh::xtended::ManSection* object = dynamic_cast<const wosh::xtended::ManSection*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = EncoderXML_template__ManItem().serializeTo( object, doc, contNode, compact );
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ManSection::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	wosh::xtended::ManSection* object = dynamic_cast<wosh::xtended::ManSection*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = EncoderXML_template__ManItem().deserializeFrom( object, contNode );

	QDomNodeList itemsList = contNode.childNodes();
	for( unsigned int j=0; j<itemsList.length(); j++ ) {
		QDomElement childNode = itemsList.item(j).toElement();

		ManItem* item = NULL;
		if ( childNode.tagName() == _Property_TYPE ) {
			item = new ManItemProperty();
			ret += EncoderXML_template__ManItemProperty().deserializeFrom( item, childNode );
		}
		else {
			item = new ManItem();
			ret += EncoderXML_template__ManItem().deserializeFrom( item, childNode );
		}

		object->getItem().set( item->getName(), item);
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ManPage::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const wosh::xtended::ManPage* object = dynamic_cast<const wosh::xtended::ManPage*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = EncoderXML_template__ManItem().serializeTo( object, doc, contNode, compact );
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ManPage::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	wosh::xtended::ManPage* object = dynamic_cast<wosh::xtended::ManPage*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	ret += EncoderXML_template__ManItem().deserializeFrom( object, contNode );

	QDomElement versionNode = contNode.namedItem("version").toElement();
	if ( versionNode.isNull() )
		object->setVersion( contNode.attribute("version").toDouble() );
	else
		object->setVersion( versionNode.text().toDouble() );

	QDomElement languageNode = contNode.namedItem("language").toElement();
	if ( languageNode.isNull() )
		object->setLanguage( string( contNode.attribute("language").toLatin1().data() ) );
	else
		object->setLanguage( string( languageNode.text().toLatin1().data() ) );

	QDomElement bodyNode = contNode.namedItem("body").toElement();
	if ( !bodyNode.isNull() ) {
		QDomNodeList sectionList = bodyNode.childNodes();
		for( unsigned int j=0; j<sectionList.length(); j++ ) {
			QDomElement childNode = sectionList.item(j).toElement();
			ManSection* section = new ManSection();
			ret += EncoderXML_template__ManSection().deserializeFrom( section, childNode );
			object->getSections().set( section->getName(), section);
		 }
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ManItemProperty::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const wosh::xtended::ManItemProperty* object = dynamic_cast<const wosh::xtended::ManItemProperty*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = EncoderXML_template__ManItem().serializeTo( object, doc, contNode, compact );

	QDomElement valueNode = doc.createElement("value");
	ret += EncoderXML_template__Variant().serializeTo( &object->getValueDefault(), doc, valueNode, compact );
	contNode.appendChild(valueNode);

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ManItemProperty::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	wosh::xtended::ManItemProperty* object = dynamic_cast<wosh::xtended::ManItemProperty*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = EncoderXML_template__ManItem().deserializeFrom( object, contNode );

	QDomElement valueNode = contNode.namedItem("value").toElement();
	if ( !valueNode.isNull() )
		ret += EncoderXML_template__Variant().deserializeFrom( &object->getValueDefault(), valueNode );
	else
		object->getValueDefault().fromString( contNode.attribute("value").toLatin1().data() );

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__WeatherInfo::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const wosh::xtended::WeatherInfo* object = dynamic_cast<const wosh::xtended::WeatherInfo*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;
	(void)compact;

	contNode.setAttribute("timestamp", QString::number( object->getTimestamp() ) );

	QDomElement periodNode = doc.createElement("period");
	periodNode.setAttribute("name", QString( object->getPeriodName().c_str() ) );
	if ( object->getPeriodStart() != 0 ) {
		QDomElement periodStartNode = doc.createElement("start");
		periodStartNode.appendChild( doc.createTextNode( QString::number(object->getPeriodStart()) ) );
		periodNode.appendChild(periodStartNode);
	 }
	if ( object->getPeriodEnd() != 0 ) {
		QDomElement periodEndNode = doc.createElement("end");
		periodEndNode.appendChild( doc.createTextNode( QString::number(object->getPeriodEnd()) ) );
		periodNode.appendChild(periodEndNode);
	 }
	contNode.appendChild(periodNode);

	QDomElement conditionNode = doc.createElement("condition");
	conditionNode.setAttribute("key", QString( object->getConditionKey().c_str() ) );
	if ( !object->getConditionSummary().empty() ) {
		QDomElement cSummaryNode = doc.createElement("summary");
		cSummaryNode.appendChild( doc.createTextNode( QString(object->getConditionSummary().c_str()) ) );
		conditionNode.appendChild(cSummaryNode);
	 }
	contNode.appendChild(conditionNode);

	QDomElement temperatureNode = doc.createElement("temperature");
	if ( object->getTemperatureHighest() != _WeatherInfo_TemperatureUndefined ) {
		QDomElement tempHighNode = doc.createElement("highest");
		tempHighNode.appendChild( doc.createTextNode( QString::number(object->getTemperatureHighest()) ) );
		temperatureNode.appendChild(tempHighNode);
	 }
	if ( object->getTemperatureLowest() != _WeatherInfo_TemperatureUndefined ) {
		QDomElement tempLowNode = doc.createElement("lowest");
		tempLowNode.appendChild( doc.createTextNode( QString::number(object->getTemperatureLowest()) ) );
		temperatureNode.appendChild(tempLowNode);
	 }
	contNode.appendChild(temperatureNode);

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__WeatherInfo::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	wosh::xtended::WeatherInfo* object = dynamic_cast<wosh::xtended::WeatherInfo*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement tsNode = contNode.namedItem("timestamp").toElement();
	if ( tsNode.isNull() )
		object->setTimestamp( contNode.attribute("timestamp").toLong() );
	else
		object->setTimestamp( tsNode.text().toLong() );

	QDomElement periodNode = contNode.namedItem("period").toElement();
	if ( !periodNode.isNull() ) {
		QDomElement pNameNode = periodNode.namedItem("name").toElement();
		if ( pNameNode.isNull() )
			object->setPeriodName( string( periodNode.attribute("name").toLatin1().data() ) );
		else
			object->setPeriodName( string( pNameNode.text().toLatin1().data() ) );

		QDomElement pStartNode = periodNode.namedItem("start").toElement();
		if ( pStartNode.isNull() )
			object->setTemperatureHighest( periodNode.attribute("start").toInt() );
		else
			object->setTemperatureHighest( pStartNode.text().toInt() );

		QDomElement pEndNode = periodNode.namedItem("end").toElement();
		if ( pEndNode.isNull() )
			object->setTemperatureHighest( periodNode.attribute("end").toInt() );
		else
			object->setTemperatureHighest( pEndNode.text().toInt() );
	 }

	QDomElement conditionNode = contNode.namedItem("condition").toElement();
	if ( !conditionNode.isNull() ) {
		QDomElement cKeyNode = conditionNode.namedItem("key").toElement();
		if ( cKeyNode.isNull() )
			object->setConditionSummary( string( conditionNode.attribute("key").toLatin1().data() ) );
		else
			object->setConditionSummary( string( cKeyNode.text().toLatin1().data() ) );

		QDomElement cSummaryNode = conditionNode.namedItem("summary").toElement();
		if ( cSummaryNode.isNull() )
			object->setConditionSummary( string( conditionNode.attribute("summary").toLatin1().data() ) );
		else
			object->setConditionSummary( string( cSummaryNode.text().toLatin1().data() ) );
	 }

	QDomElement tempNode = contNode.namedItem("temperature").toElement();
	if ( !tempNode.isNull() ) {
		QDomElement tempHighNode = tempNode.namedItem("highest").toElement();
		if ( tempHighNode.isNull() )
			object->setTemperatureHighest( tempNode.attribute("highest").toInt() );
		else
			object->setTemperatureHighest( tempHighNode.text().toInt() );

		QDomElement tempLowNode = tempNode.namedItem("lowest").toElement();
		if ( tempLowNode.isNull() )
			object->setTemperatureLowest( tempNode.attribute("lowest").toInt() );
		else
			object->setTemperatureLowest( tempLowNode.text().toInt() );
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 }; // namespace database
}; // namespace wosh
